/*
\ brief:   实现文件
\ author: 清晨与猫鱼
*/
#include <iostream>     // 引入标准输入输出库
#include <memory>       // 引入内存管理库
#include <string>       // 引入字符串库

using namespace std;       // 引入标准空间


/*
\ brief:  抽象继承接口类
\ author: 清晨与猫鱼
*/
class AbstractLogger {
public:

/*
\ brief:  构造函数 设置当前对象的处理等级
\ author: 清晨与猫鱼
*/
    explicit AbstractLogger(int level)
        : level_(level){
    }

/*
\ brief:  设置下一个处理的对象
\ author: 清晨与猫鱼
*/
    void setNextLogger(AbstractLogger* nextLogger) {
        nextLogger_.reset(nextLogger);
    }

/*
\ brief:  处理消息
\ author: 清晨与猫鱼
*/
    void logMessage(int level, string message) {
        // 判断是否能够处理消息
        if (level_ <= level) {
            write(message);
        }

        // 如果下一个处理对象存在，那么传递消息
        if (nextLogger_) {            
            nextLogger_->logMessage(level, message);
        }
    }

public:
    static int INFO;        // 普通信息权限
    static int DEBUG;       // 调试信息权限
    static int ERROR;       // 错误消息权限
protected:
    virtual void write(string message) = 0;     // 接口函数，处理消息

protected:
    int level_;     // 等级权限
    unique_ptr<AbstractLogger> nextLogger_;     // 下一个处理对象
};

// 设置权限等级
int AbstractLogger::INFO = 1;
int AbstractLogger::DEBUG = 2;
int AbstractLogger::ERROR = 3;


/*
\ brief:  控制台消息处理
\ author: 清晨与猫鱼
*/
class ConsoleLogger 
    : public AbstractLogger {
public:
    explicit ConsoleLogger(int level) 
        : AbstractLogger(level){        
    }
    
    void write(string message) {
        cout << "Standard Console::Logger: " << message << endl;
    }
};


/*
\ brief:  错误消息处理
\ author: 清晨与猫鱼
*/ 
class ErrorLogger 
    : public AbstractLogger {
public:
    explicit ErrorLogger(int level)
        : AbstractLogger(level) {
    }

    void write(string message) {
        cout << "Error Console::Logger: " << message << endl;
    }
};


/*
\ brief:  文件消息错误
\ author: 清晨与猫鱼
*/
class FileLogger 
    : public AbstractLogger {
public:
    explicit FileLogger(int level)
        : AbstractLogger(level) {
    }

    void write(string message) {
        cout << "File::Logger: " << message << endl;
    }
};